using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;


namespace MIMP
{
    /// <summary>
    /// A popup message box screen, used to display both informational messages and confirm/cancel dialogs.
    /// </summary>
    class MessageBoxScreen : GameScreen
    {


        string message;
        Texture2D gradientTexture;
        UIButtonDisplay ok;
        UIButtonDisplay cancel;
        Vector2 textPosition;
        Rectangle backgroundRectangle;
        bool includeCancel;

        public event EventHandler<EventArgs> Accepted;
        public event EventHandler<EventArgs> Cancelled;


        /// <summary>
        /// Constructs a new MessageBoxScreen with an OK button and a Cancel button.
        /// </summary>
        public MessageBoxScreen(string message)
            : this(message, true)
        { }


        /// <summary>
        /// Constructs a new MessageBoxScreen with an OK button, and optionally a Cancel button.
        /// </summary>
        public MessageBoxScreen(string message, bool includeCancelButton)
        {
            this.includeCancel = includeCancelButton;
            this.message = message;

            IsPopup = true;

            TransitionOnTime = TimeSpan.FromSeconds(0.2);
            TransitionOffTime = TimeSpan.FromSeconds(0.2);
        }


        /// <summary>
        /// Loads graphics content for this screen. This uses the shared ContentManager
        /// provided by the Game class, so the content will remain loaded forever.
        /// Whenever a subsequent MessageBoxScreen tries to load this same content,
        /// it will just get back another reference to the already loaded data.
        /// </summary>
        public override void LoadContent()
        {
            ContentManager content = ScreenManager.Game.Content;

            gradientTexture = content.Load<Texture2D>(MIMPGame.CONTENT_DIR + "blank");
            Texture2D check = content.Load<Texture2D>(MIMPGame.CONROL_PANEL_SPRITES_DIR + "check-button");
            Texture2D canc = content.Load<Texture2D>(MIMPGame.CONROL_PANEL_SPRITES_DIR + "cancel-button");
            ok = new UIButtonDisplay(0, 0, 1, check, Keys.Enter, UIButtons.EndTurn);
            cancel = new UIButtonDisplay(0, 0, 1, canc, Keys.Escape, UIButtons.Menu);
        }

        /// <summary>
        /// Responds to user input, accepting or cancelling the message box.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            SetCoords();
            ok.SetIsMouseOver(input.CurrentMouseState);
            cancel.SetIsMouseOver(input.CurrentMouseState);
            if (input.IsNewKeyRelease(ok.ShortcutKey) || (input.IsNewLeftMouseClick() && ok.IsMouseOver))
            {
                // Raise the accepted event, then exit the message box.
                if (Accepted != null)
                    Accepted(this, EventArgs.Empty);

                ExitScreen();
            }
            else if (input.IsNewKeyRelease(cancel.ShortcutKey) || (input.IsNewLeftMouseClick() && cancel.IsMouseOver))
            {
                // Raise the cancelled event, then exit the message box.
                if (Cancelled != null)
                    Cancelled(this, EventArgs.Empty);

                ExitScreen();
            }
        }

        void SetCoords()
        {
            SpriteFont font = ScreenManager.MessageBoxFont;
            // Center the message text in the viewport.
            Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
            Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
            Vector2 textSize = font.MeasureString(message);
            textPosition = (viewportSize - textSize) / 2;

            // The background includes a border somewhat larger than the text itself.
            int hPad = ok.Sprite.Width / 2;
            int vPad = ok.Sprite.Height;

            backgroundRectangle = new Rectangle((int)textPosition.X - hPad,
                                                          (int)textPosition.Y - vPad,
                                                          (int)textSize.X + hPad * 2,
                                                          (int)textSize.Y + vPad * 2);
            textPosition.Y -= ok.Sprite.Height;

            if (includeCancel)
            {
                ok.Origin = new Vector2(backgroundRectangle.Left + ok.Sprite.Width / 2, backgroundRectangle.Bottom - ok.Sprite.Height * 3 / 2);
                
                cancel.Origin = new Vector2(backgroundRectangle.Right - cancel.Sprite.Width * 3 / 2, backgroundRectangle.Bottom - cancel.Sprite.Height * 3 / 2);
            }
            else
            {
                ok.Origin = new Vector2(backgroundRectangle.Left + backgroundRectangle.Width / 2 - ok.Sprite.Width / 2, 
                    backgroundRectangle.Bottom - ok.Sprite.Height * 4 / 3);
            }
        }

        /// <summary>
        /// Draws the message box.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            SpriteFont font = ScreenManager.MessageBoxFont;

            // Darken down any other screens that were drawn beneath the popup.
            ScreenManager.FadeBackBufferToBlack(TransitionAlpha * 2 / 3);

            // Fade the popup alpha during transitions.
            float alpha = TransitionAlpha / 255;
            Color color = new Color(255, 255, 255, TransitionAlpha);
            Color textColor = new Color(0, 0, 0, TransitionAlpha);
            spriteBatch.Begin();

            // Draw the background rectangle.
            spriteBatch.Draw(gradientTexture, backgroundRectangle, color);

            // Draw the message box text.
            spriteBatch.DrawString(font, message, textPosition, textColor);

            // Draw the buttons.
            if (includeCancel)
            {
                spriteBatch.Draw(ok.Sprite, ok.Origin, color);
                spriteBatch.Draw(cancel.Sprite, cancel.Origin, color);
            }
            else
            {
                spriteBatch.Draw(ok.Sprite, ok.Origin, color);
            }

            spriteBatch.End();
        }
    }
}
